package at.ac.tuwien.dse.health.portal;

import at.ac.tuwien.dse.health.portal.dto.ReservedSurgerySlotDTO;
import at.ac.tuwien.dse.health.shared.FilterSettings;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.inject.Inject;
import javax.servlet.http.HttpSession;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import static org.apache.commons.lang3.ObjectUtils.firstNonNull;
import static org.apache.commons.lang3.StringUtils.*;

/**
 * @author Bernhard Nickel
 * @author Gregor Schauer
 * @author Dominik Strasser
 */
@Controller
public class PortalController {

	@Inject
	private JdbcTemplate jdbcTemplate;

	@RequestMapping(value = "/welcome", method = RequestMethod.GET)
	public ModelAndView portal(HttpSession session) {
		return new ModelAndView("portal").addObject("filters",getFilterSettings(session));
	}

	@RequestMapping(value = "/data", method = RequestMethod.GET)
	@ResponseBody
	@Transactional(readOnly = true, isolation = Isolation.READ_COMMITTED)
	public List<ReservedSurgerySlotDTO> getSlots(@RequestParam(required = false) String hospital,
												   @RequestParam(required = false) String type,
												   @RequestParam(required = false) Date date,
												   final Locale locale, HttpSession session) {

		FilterSettings settings = getFilterSettings(session);
		settings.setHospital(defaultIfBlank(hospital, settings.getHospital()));
		settings.setSurgeryType(defaultIfBlank(type, settings.getSurgeryType()));
		settings.setDate(firstNonNull(date, settings.getDate()));

		List<Object> args = new ArrayList<Object>(3);
		String sql = "SELECT * FROM surgeryslot_overview WHERE time_start >= ?";
		args.add(firstNonNull(settings.getDate(), new Date()));

		if (isNotBlank(settings.getSurgeryType())) {
			sql += " AND type = ?";
			args.add(settings.getSurgeryType());
		}
		if (isNotBlank(settings.getHospital())) {
			sql += " AND hospital = ?";
			args.add(settings.getHospital());
		}

		return jdbcTemplate.query(sql, args.toArray(), new RowMapper<ReservedSurgerySlotDTO>() {
			@Override
			public ReservedSurgerySlotDTO mapRow(ResultSet rs, int rowNum) throws SQLException {
				String doctor = rs.getString("doctor");
				return new ReservedSurgerySlotDTO(locale, rs.getDate("time_start"), rs.getDate("time_end"),
						rs.getString("type"), rs.getString("hospital"), doctor, isBlank(doctor));
			}
		});
	}

	@RequestMapping(value = "/surgeryTypes", method = RequestMethod.GET)
	@ResponseBody
	@Transactional(readOnly = true, isolation = Isolation.READ_COMMITTED)
	public List<String> getAvailableSurgeryTypes() {
		List<String> types = jdbcTemplate.queryForList("SELECT name FROM department ORDER BY name", String.class);
		types.add(0, "");
		return types;
	}

	@RequestMapping(value = "/hospitals", method = RequestMethod.GET)
	@ResponseBody
	@Transactional(readOnly = true, isolation = Isolation.READ_COMMITTED)
	public List<String> getAvailableHospitals() {
		List<String> hospitals = jdbcTemplate.queryForList("SELECT name FROM hospital ORDER BY name", String.class);
		hospitals.add(0, "");
		return hospitals;
	}

	@RequestMapping(value = "/filter", method = RequestMethod.GET)
	@ResponseBody
	public void setFilter(@RequestParam("filterKey") String key, @RequestParam("filterValue") String value, HttpSession session) {
		FilterSettings settings = getFilterSettings(session);
		if (key.equalsIgnoreCase("DATE")) {
			settings.setDate(new Date(Long.valueOf(value)));
		} else if (key.equalsIgnoreCase("SURGERY_TYPE")) {
			settings.setSurgeryType(value);
		} else if (key.equalsIgnoreCase("HOSPITAL")) {
			settings.setHospital(value);
		}
	}

	FilterSettings getFilterSettings(HttpSession session) {
		FilterSettings settings = session == null ? new FilterSettings()
				: (FilterSettings) session.getAttribute(FilterSettings.SESSION_ATTRIBUTE_NAME);
		if (settings == null) {
			settings = new FilterSettings();
			session.setAttribute(FilterSettings.SESSION_ATTRIBUTE_NAME, settings);
		}
		return settings;
	}
}
